package com.itheima.service.impl;

import com.itheima.common.constant.MessageConstant;
import com.itheima.common.exception.FileDownloadFailException;
import com.itheima.mapper.MemberMapper;
import com.itheima.mapper.OrderMapper;
import com.itheima.mapper.SetmealMapper;
import com.itheima.pojo.*;
import com.itheima.service.ReportService;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ReportServiceImpl implements ReportService {

    @Autowired
    private SetmealMapper setmealMapper;
    @Autowired
    private MemberMapper memberMapper;
    @Autowired
    private OrderMapper orderMapper;

    /**
     * 获取套餐占比统计数据
     * @return
     */
    @Override
    public SetmealReportVO getSetmealReport() {
        // 获取所有的套餐名称和被预约的数量
        List<SetmealCount> counts = setmealMapper.selectSetmealNameAndCount(null);
        if (counts == null || counts.isEmpty()){
            return new SetmealReportVO(Collections.singletonList("暂无数据"), Collections.singletonList(new SetmealCount("暂无数据", 1)));
        }
        // 封装数据
        return new SetmealReportVO(counts.stream().map(SetmealCount::getName).collect(Collectors.toList()), counts);
    }

    /**
     * 获取会员数量统计数据
     * @return
     */
    @Override
    public MemberReportVO getMemberReport() {
        // 获取今天的日期
        LocalDate today = LocalDate.now();
        // 定义集合记录数据
        List<String> months = new ArrayList<>();
        List<Integer> memberCount = new ArrayList<>();
        // 设置日期格式化器
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy.MM.dd");
        for (int index = 11; index >= 0; index--) {
            // 获取截至次月第一天前的会员数量
            Integer count = memberMapper.selectMemberCountByMonth(today.plusMonths(1 - index).withDayOfMonth(1));
            memberCount.add(count);
            months.add(today.plusMonths(1 - index).withDayOfMonth(1).minusDays(1).format(df));
        }
        return new MemberReportVO(months, memberCount);
    }

    /**
     * 获取运营数据统计
     * @return
     */
    @Override
    public BusinessReportVO getBusinessReport() {
        // 获取今日日期
        LocalDate today = LocalDate.now();
        // 所有日期范围查询包前不包后
        // 查询今日的相关数据
        Map<String, Integer> todayDate = getDate4Period(today, today.plusDays(1));

        // 查询本周的相关数据
        Map<String, Integer> thisWeekDate = getDate4Period(today.with(DayOfWeek.MONDAY), today.with(DayOfWeek.SUNDAY).plusDays(1));

        // 查询本月的相关数据
        Map<String, Integer> thisMonthDate = getDate4Period(today.withDayOfMonth(1), today.withDayOfMonth(today.lengthOfMonth()).plusDays(1));

        // 查询热门套餐top4
        List<SetmealCount> setmeals = setmealMapper.selectSetmealNameAndCount(4);
        // 查询总预约数量
        Integer totalOrder = orderMapper.countAll();
        List<HotSetmeal> hotSetmeals = new ArrayList<>();
        for (SetmealCount item : setmeals) {
            Double proportion = item.getValue() * 1.0 / totalOrder * 100;
            BigDecimal bd = new BigDecimal(proportion).setScale(2, RoundingMode.HALF_UP);
            hotSetmeals.add(new HotSetmeal(item.getName(), item.getValue(), bd.doubleValue()));
        }
        // 查询会员总数
        Integer totalMember = memberMapper.selectMemberCountByMonth(today.plusDays(1));

        // 封装数据
        return new BusinessReportVO(today,
                todayDate.get("orderNumber"),todayDate.get("visitsNumber"),todayDate.get("newMember"),
                thisWeekDate.get("orderNumber"),thisWeekDate.get("visitsNumber"),thisWeekDate.get("newMember"),
                thisMonthDate.get("orderNumber"),thisMonthDate.get("visitsNumber"),thisMonthDate.get("newMember"),
                hotSetmeals,totalMember);
    }

    /**
     * 导出运营数据
     */
    @Override
    public void exportBusinessReport(HttpServletResponse response) {
        try(
                // 获取模板文件输入流
                InputStream is = this.getClass().getClassLoader().getResourceAsStream("templates/report_template.xlsx");
                // 创建输出流
                ServletOutputStream os = response.getOutputStream();
        ){
            // 设置响应类型
            response.setContentType("application/vnd.ms-excel");
            // 获取运营数据
            BusinessReportVO businessReportVO = getBusinessReport();
            // 创建一个基于is的工作簿对象
            XSSFWorkbook workbook = new XSSFWorkbook(is);
            // 获取第一个sheet页
            XSSFSheet sheet = workbook.getSheetAt(0);
            // 填充日期信息
            sheet.getRow(2).getCell(5).setCellValue(String.valueOf(businessReportVO.getReportDate()));
            // 填充其他信息
            sheet.getRow(4).getCell(5).setCellValue(businessReportVO.getTodayNewMember());
            sheet.getRow(4).getCell(7).setCellValue(businessReportVO.getTotalMember());
            sheet.getRow(5).getCell(5).setCellValue(businessReportVO.getThisWeekNewMember());
            sheet.getRow(5).getCell(7).setCellValue(businessReportVO.getThisMonthNewMember());
            // 填充今日相关数据
            sheet.getRow(7).getCell(5).setCellValue(businessReportVO.getTodayOrderNumber());
            sheet.getRow(7).getCell(7).setCellValue(businessReportVO.getTodayVisitsNumber());
            // 填充本周相关数据
            sheet.getRow(8).getCell(5).setCellValue(businessReportVO.getThisWeekOrderNumber());
            sheet.getRow(8).getCell(7).setCellValue(businessReportVO.getThisWeekVisitsNumber());
            // 填充本月相关数据
            sheet.getRow(9).getCell(5).setCellValue(businessReportVO.getThisMonthOrderNumber());
            sheet.getRow(9).getCell(7).setCellValue(businessReportVO.getThisMonthVisitsNumber());
            // 填充热门套餐数据
            List<HotSetmeal> hotSetmeals = businessReportVO.getHotSetmeal();
            for (int i = 0; i < hotSetmeals.size(); i++) {
                HotSetmeal item = hotSetmeals.get(i);
                sheet.getRow(12 + i).getCell(4).setCellValue(item.getName());
                sheet.getRow(12 + i).getCell(5).setCellValue(item.getSetmeal_count());
                sheet.getRow(12 + i).getCell(6).setCellValue(item.getProportion());
            }
            workbook.write(os);
            workbook.close();
        }catch (Exception e){
            throw new FileDownloadFailException(MessageConstant.GET_BUSINESS_REPORT_FAIL);
        }
    }


    /**
     * 根据指定的日期范围查询预约数量和到诊数量以及新增会员数量
     * @param begin
     * @param end
     * @return
     */
    public Map<String,Integer> getDate4Period(LocalDate begin,LocalDate end){
        Map<String,Integer> map = new HashMap<>();
        // 获取查询预约状态和数量
        List<OrderStatusCount> list = orderMapper.countOrderByDate(begin, end);
        Integer orderNumber = 0;
        Integer visitsNumber = 0;
        if (list != null && !list.isEmpty()){
            for (OrderStatusCount item : list) {
                if (Order.ORDERSTATUS_YES.equals(item.getStatus())){
                    visitsNumber += item.getCount();
                }
                orderNumber += item.getCount();
            }
        }
        // 获取新增会员数量
        Integer newMember = memberMapper.countMemberByDate(begin, end);
        // 封装数据
        map.put("orderNumber",orderNumber);
        map.put("visitsNumber",visitsNumber);
        map.put("newMember",newMember);
        return map;
    }
}
